package com.googlecode.cnasort.cc.rmi.client;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.rmi.NotBoundException;
import org.apache.log4j.Logger;
import com.googlecode.cnasort.cc.rmi.client.core.FileLoaderClientCore;
import com.googlecode.cnasort.cc.rmi.client.core.FileLoaderClientCoreV0Impl;
import com.googlecode.cnasort.cc.rmi.common.ClientRmiStarter;
import com.googlecode.cnasort.cc.rmi.common.RMIFileLoaderConnectorV0;
import com.lexicalscope.jewel.cli.CliFactory;
import com.lexicalscope.jewel.cli.Option;

public class MyRmiClient extends ClientRmiStarter<RMIFileLoaderConnectorV0>
{
    private static final Logger logger = Logger.getLogger( MyRmiClient.class );

    public enum Command {
        dir, download, quit
    }

    public interface CLIOptions
    {
        @Option(defaultValue="localhost") String getHost();

        @Option String getLogFilename();
        boolean isLogFilename();

        @Option String getCommand();

        @Option String getDirName();
        boolean isDirName();
    }

    public static void main( final String[] args ) throws NotBoundException, IOException
    {
         final CLIOptions result = CliFactory.parseArguments(CLIOptions.class, args);
         final Command command;
         final String  dirName;

        switch( result.getCommand().toLowerCase() ) {
         case "quit" :
             command = Command.quit;
             dirName = null;
             break;

         case "download" :
             command = Command.download;
             dirName = result.getDirName();
             break;

         default:
             command = Command.dir ;
             dirName = null;
             break;
         }

        MyRmiClient client = new MyRmiClient( RMIFileLoaderConnectorV0.class, result.getHost() );
        
        client.connect( result.getLogFilename(), command, dirName );
    }

    private static void handle(
            final RMIFileLoaderConnectorV0 c,
            final Command                command,
            final String                 prefixToDownload,
            final PrintStream            out
            ) throws IOException
        {
        logger.info("Found expected service: RMIFileLoaderConnectorV0");

            FileLoaderClientCore instance = new FileLoaderClientCoreV0Impl( c, out, new File( "dl" ), new DefaultExoRmiClientCoreFilters() );

            switch( command ) {
                case dir:
                    instance.printDirectoriesAndFiles();
                    break;
                case download:
                    instance.doDownload( prefixToDownload );
                    break;
                case quit:
                    instance.doQuit();
                    break;
                }
        }

//    private static void handle(
//        final RMIFileLoaderConnector c,
//        final Command                command,
//        final String                 prefixToDownload,
//        final PrintStream            out
//        ) throws IOException
//    {
//        logger.info("Found expected service: RMIFileLoaderConnector");
//
//        FileLoaderClientCore instance = new FileLoaderClientCoreImpl( c, out, new File( "dl" ), new DefaultExoRmiClientCoreFilters() );
//
//        switch( command ) {
//            case dir:
//                instance.printDirectoriesAndFiles();
//                break;
//            case download:
//                instance.doDownload( prefixToDownload );
//                break;
//            case quit:
//                instance.doQuit();
//                break;
//            }
//    }

    private static String getClassname(Object o)
    {
        return o == null ? "NULL" : o.getClass().toString();
    }

    public MyRmiClient(
        final Class<RMIFileLoaderConnectorV0> clazzToAddToServerCodebase,
        final String                          hostName
        )
    {
        super( clazzToAddToServerCodebase, false, hostName, RMIFileLoaderConnectorV0.SERVICE_NAME );
    }

    public void connect(
            //final String  serverName,
            final String  logFilename,
            final Command command,
            final String  prefixToDownload
            ) throws NotBoundException, IOException
    {
        PrintStream log = System.out;
        PrintStream out;

        if( logFilename != null ) {
            @SuppressWarnings("resource") // Closed !
            PrintStream outFile = new PrintStream( new FileOutputStream(logFilename, true ) );
            out = outFile;
            }
        else {
            out = System.out;
            }


        try {
            RMIFileLoaderConnectorV0 object = lookup();

            logger.info("Connected to server." );
            logger.info("Class = " + getClassname( object ) );
            logger.info("object = " + object );

//            if( object != null ) {
//                Class<?> clazz = object.getClass();
//
//                while( clazz != null ) {
//                    logger.info("class: " + clazz );
//
//                    for( Class<?> i : clazz.getInterfaces() ) {
//                        logger.info("interface : " + i );
//                        }
//                    clazz = clazz.getSuperclass();
//                    }
//                }

            if( object instanceof RMIFileLoaderConnectorV0 ) {
                handle( (RMIFileLoaderConnectorV0)object, command, prefixToDownload, out );
                }
//            if( object instanceof RMIFileLoaderConnector ) {
//                handle( (RMIFileLoaderConnector)object, command, prefixToDownload, out );
//                }
//            else {
//                logger.info("Expected service NOT FOUND.");
//
//                System.err.println("Expected service NOT FOUND.");
//                System.err.flush();
//                }
            }
        finally {
            if( log != null ) {
                log.close();
                }
            }
    }
}
